package com.bpr.webservice.controller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.bpr.webservice.controller.util.Constants;
import com.bpr.webservice.domain.Menu;
import com.bpr.webservice.domain.Menuaccess;
import com.bpr.webservice.domain.Users;
import com.bpr.webservice.domain.dto.JSTreeMenuDTO;
import com.bpr.webservice.domain.dto.MenuaccessDto;
import com.bpr.webservice.domain.dto.MenuaccessPageDto;
import com.bpr.webservice.repository.MenuRepository;
import com.bpr.webservice.repository.MenuaccessRepository;
import com.bpr.webservice.repository.UsersRepository;

@Controller
@RequestMapping("/menuaccess")
public class MenuaccessController {

	@Autowired MenuaccessRepository menuaccessRepository;
	@Autowired MenuRepository menuRepository;
	@Autowired UsersRepository usersRepository;
	
	@RequestMapping(value = "/save", method = RequestMethod.POST)
	public ResponseEntity<String> doSave(
				@RequestParam(value = "userid", required=false) Long userId,
				@RequestParam(value = "menuid", required = false) Long[] menuIds
			) {
		
		// delete all menuaccess based on user
		Users user = usersRepository.findByUserId(userId);
		for (Menuaccess ma:user.getMenuaccessList()){
			menuaccessRepository.delete(ma);
		}
		
		for (Long menuid:menuIds){
			Menu menu = menuRepository.findOne(menuid);
			
			if (menu != null && user != null){			
				Menuaccess ma = new Menuaccess();
				ma.setMenuid(menu);
				ma.setUserid(user);
				ma.setLevels(0);
				ma.setParent(0);
				
				menuaccessRepository.save(ma);
			}
		}

		return new ResponseEntity<String>(Constants.CRUD_MESSAGE.SAVE_SUCCED,
				HttpStatus.OK);
	}

	@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
	public ResponseEntity<String> doDelete(@PathVariable("id") Long id) {
		try {
			menuaccessRepository.delete(id);
		} catch (Exception ex) {
			return new ResponseEntity<String>(ex.getMessage(),
					HttpStatus.EXPECTATION_FAILED);
		}

		return new ResponseEntity<String>(Constants.CRUD_MESSAGE.SAVE_SUCCED,
				HttpStatus.OK);
	}

	@RequestMapping(value = "/findone/{id}", method = RequestMethod.GET)
	public @ResponseBody
	MenuaccessDto getOne(@PathVariable("id") Long id) {
		Menuaccess user = menuaccessRepository.findOne(id);
		MenuaccessDto dto = new MenuaccessDto();
		if (user != null) {
			dto.constructDto(user);
		}

		return dto;
	}

	@RequestMapping(value = "/search/{page}/{size}")
	public @ResponseBody
	Page<MenuaccessDto> findAll(@PathVariable("page") Integer page,
			@PathVariable("size") Integer size) {
		Page<Menuaccess> searchResult = menuaccessRepository.findAll(new PageRequest(
				page, size));
		Page<MenuaccessDto> dtoResult = new MenuaccessPageDto(searchResult);
		return dtoResult;
	}
	
	@RequestMapping("/getmenu")
	public @ResponseBody List<JSTreeMenuDTO> getMenus(
				@RequestParam(value="id", required=false) Long id,
				@RequestParam(value="precheck[]", required=false) Long[] ids,
				@RequestParam(value="checklogged", required=false) Boolean logged,
				HttpServletRequest request
			){
		List<JSTreeMenuDTO> menu = new ArrayList<JSTreeMenuDTO>();
		List<JSTreeMenuDTO> parent = new ArrayList<JSTreeMenuDTO>();
		List<JSTreeMenuDTO> level1 = new ArrayList<JSTreeMenuDTO>();
		List<JSTreeMenuDTO> level2 = new ArrayList<JSTreeMenuDTO>();
		
		List<Menu> menus = menuRepository.findAll();
		
		for (Menu m : menus){
			JSTreeMenuDTO all = new JSTreeMenuDTO();
			Map<String, Object> attr = new HashMap<String, Object>();
			Map<String, Object> data = new HashMap<String, Object>();
			Map<String, Object> dataAttr = new HashMap<String, Object>();	
			
			attr.put("id", m.getMenuid());
						
			if (logged == null){ // for menu access
				if (Arrays.asList(ids).contains(m.getMenuid())){
					attr.put("class", "jstree-checked");
				}
			} else if (logged != null & logged == true){ // main menu
				Authentication auth = SecurityContextHolder.getContext().getAuthentication();
				Users loggedUser = usersRepository.authenticate(auth.getName());
				List<Long> loggedMenuId = new ArrayList<Long>();
				for(Menuaccess ma:loggedUser.getMenuaccessList()){
					loggedMenuId.add(ma.getMenuid().getMenuid());
				}
				
				if (loggedMenuId.contains(m.getMenuid())){
					if (!m.getLink().equals("#")){
						dataAttr.put("href", request.getServletContext().getContextPath() + m.getLink());						
					} else {
						dataAttr.put("href", "#");
					}

					data.put("attr", dataAttr);
					data.put("title", m.getMenuname());
				} else {
					dataAttr.put("href", "#");
					data.put("attr", dataAttr);
					data.put("title", m.getMenuname());
					if(m.getLevels().equals(2)){
						attr.put("rel", "disabled-leaf");
					}
					
				}
			}
			
			all.setMenuid(m.getMenuid());
			all.setData(data);
			all.setLink(m.getLink());		
			all.setParent(m.getParent());
			all.setAttr(attr);			
			
			
			if( m.getLevels().equals(0) ){
				all.setState(JSTreeMenuDTO.STATE_OPEN);
				parent.add(all);				
			} else if (m.getLevels().equals(1)){				
				all.setState(JSTreeMenuDTO.STATE_OPEN);
				level1.add(all);
			} else {				
				level2.add(all);			
				
			}
		}
		
		
		
		for (JSTreeMenuDTO l1: level1){
			List<JSTreeMenuDTO> tmp = new ArrayList<JSTreeMenuDTO>();
			for (JSTreeMenuDTO c: level2){
				if (c.getParent() == NumberUtils.toInt(String.valueOf(l1.getMenuid()))){
					tmp.add(c);
				}
			}
			l1.setChildren(tmp);
		}
		
		for (JSTreeMenuDTO p : parent) {
			List<JSTreeMenuDTO> tmp = new ArrayList<JSTreeMenuDTO>();
			for (JSTreeMenuDTO c : level1) {
				if(c.getParent() == NumberUtils.toInt(String.valueOf(p.getMenuid()))){
					tmp.add(c);	
				}
			}
			p.setChildren(tmp);
		}
		
		menu.addAll(parent);
				
		return menu;
	}
	
	@RequestMapping(value = "/form.html")
	public String doForm(
			@RequestParam("itemId") Long itemid,
			Model model
			){
		Users user = usersRepository.findByUserId(itemid);
		model.addAttribute("user", user);
		StringBuilder sb = new StringBuilder();
		for (Menuaccess ma:user.getMenuaccessList()){
			sb.append(",").append(ma.getMenuid().getMenuid());
		}
		String grantedMenu = "[" +  ((sb.toString().isEmpty()) ? "-1" : sb.toString().substring(1)) + "]";
		model.addAttribute("granted", grantedMenu);
		
		return "menuaccess_form";
	}
	
	@RequestMapping(value = "/list.html")
	public String doList(){
		return "menuaccess_list";
	}
}
